//
// Created by mongobaba on 2021/6/8.
//

#include "unit_test.h"
#include "cJSON.h"
#include "json_validator.h"
#include "json_checker_wrapper.h"
#include <chrono>

namespace {
    const char* const goodJson =
            R"({
            "Longitude": 111.111,
            "Latitude": 23.333,
            "Orientation": 31,
            "Speed": 100,
            "Type": "4",
            "DateTime": 1491030009,
            "DeviceIdentify": "1",
            "Extend":{
                "Name": "李警官",
                "Police_Num": "12345",
                "Phone": "110",
                "Department": "广州市黄埔区xx派出所",
                "DeptNum": "001"
            }
        })";

    constexpr int REPEAT_TIME = 100000;
}

template<typename T, size_t N = 3>
std::string pretty_format(T value) {
    std::string s = std::to_string(value);
    std::string result;
    auto n = s.size() % N;
    if (n > 0) {
        result += s.substr(0, n);
        result += ',';
    }
    while (n < s.size()) {
        result += s.substr(n, N);
        result += ',';
        n += N;
    }
    result.pop_back();  // 删除最后多余的逗号
    return result;
}

TEST(pretty_format) {
    ASSERT_EQ(std::string("12"), pretty_format(12));
    ASSERT_EQ(std::string("123"), pretty_format(123));
    ASSERT_EQ(std::string("1,234"), pretty_format(1234));
    ASSERT_EQ(std::string("123,456"), pretty_format(123456));
}

template<typename F>
void run_benchmark(const char* tag, int repeat_time, F f) {
    int n = 0;
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < repeat_time; ++i) {
        if (f()) {
            n += 1;
        }
    }
    auto stop = std::chrono::high_resolution_clock::now();
    std::cout << tag << " : " << n << " times, cost " << pretty_format((stop - start).count()) << std::endl;
}

TEST(cjson_benchmark) {
    run_benchmark("cJSON", REPEAT_TIME, []{
        cJSON *p = cJSON_Parse(goodJson);
        bool success = p != nullptr;
        cJSON_Delete(p);
        return success;
    });
}

TEST(json_validator_benchmark_copy_string) {
    run_benchmark("json_validator[copy string]", REPEAT_TIME, []{
        json_validator validator(goodJson);
        return validator.parse_json();
    });
}

TEST(json_validator_benchmark_without_copy_string) {
    run_benchmark("json_validator[without copy]", REPEAT_TIME, [] {
        return json_validator::validate(goodJson);
    });
}

TEST(json_checker_wrapper_benchmark) {
    run_benchmark("json_checker_wrapper", REPEAT_TIME, [] {
        return check_by_json_checker(goodJson);
    });
}
